import logging

from flask import request, abort
from flask_classy import FlaskView, route

from ..models.metadata import Metadata
from ..models.product import Product, ProductMetadata, ProductContent
from ..schema.error import LOCAL_BRAN_NOT_EXIST, CURRENCY_NOT_EXIST, PRODUCT_CATEGORY_NOT_EXIST, METADATA_NOT_FULL
from ..schema.param import product_filter_param, product_create_param
from ..schema.resp import Product as ProductSchema, Offer as OfferSchema
from ..schema.resp import query_schema, product_schema, offer_list_schema
from ..services.brand import BrandService
from ..services.currency import CurrencyService
from ..services.language import LanguageService
from ..services.metadata import MetadataService
from ..services.offer import OfferService
from ..services.product import ProductService
from ..services.resource import ResourceService

logger = logging.getLogger(__name__)


class ProductsView(FlaskView):
    @route('/<id>')
    def get(self, id):
        return product_schema.jsonify(ProductService.get_by_id(id))

    @route('/<id>/offers')
    def get_offers(self, id):
        product = ProductService.get_by_id(id)
        if not product:
            abort(404)
        offers = OfferService.get_offer_by_product(product)
        return query_schema.jsonify_with(items=offer_list_schema.dump(offers).data)

    @route('/<product_id>/offers', methods=['GET'])
    def fetch_product_offers(self, product_id):
        product = ProductService.get_by_id(product_id)
        if not product:
            abort(404)
        currency_code = request.args.get('currency', None)
        if currency_code:
            currency = CurrencyService.get_currency_by_id(currency_code)
            if not currency:
                abort(400)
        else:
            currency = CurrencyService.get_main_currency()

        offer_list = OfferService.get_offer_by_product(product)

        # 交易推荐服务，暂时已offer里的mask字段标记
        if offer_list and len(offer_list) > 0:
            special_offer = None
            for offer in offer_list:
                if offer.mask and offer.mask.find('R') > 0:
                    special_offer = offer
                    break
            if not special_offer:
                special_offer = offer_list[0]
            from mall.services.additional_item import AdditionalItemService

            additional = []
            for addon in ['trs']:
                additional_item = AdditionalItemService.get_item_by_id(addon)
                if additional_item:
                    # additional_item.calculate_amount(currency, offer.price)
                    additional.append(additional_item)
            special_offer.additional = additional

            offer_list_schema = OfferSchema(many=True)
            offer_list_schema.context = {'currency': currency}
            return query_schema.jsonify_with(items=offer_list_schema.dump(offer_list).data)
        else:
            return query_schema.jsonify_with(items=[])

    @route("/", methods=['GET'])
    def fetch_product(self):
        name = request.args.get('name')
        language_code = request.args.get('language', None)
        currency = request.args.get('currency', None)

        if language_code:
            language = LanguageService.get_by_id(language_code)
            if not language:
                abort(400)
        if currency:
            currency = CurrencyService.get_currency_by_id(currency)
            if not currency:
                abort(400)
        product = ProductService.get(name=name)

        if product:
            product_schema = ProductSchema()
            product_schema.context = {'language': language_code, 'currency': currency}
            return product_schema.jsonify(product)
        abort(404)

    @route('/', methods=['POST'])
    def create(self):
        data, errors = product_create_param.load(request.get_json())

        category = ProductService.get_category_by_id(data.get('category_id'))
        if not category:
            return PRODUCT_CATEGORY_NOT_EXIST.jsonify()

        contents = data.pop('content')
        metadata_value = data.pop('metadata')
        cover_resource_id = data.pop('cover_resource_id')
        brand_id = data.pop('brand_id')
        brand = BrandService.get_brand_by_id(brand_id)
        if not brand:
            return LOCAL_BRAN_NOT_EXIST.jsonify()
        # tags = data.pop('tags')
        cover = ResourceService.get_by_id(cover_resource_id)
        if not cover:
            pass
        metadata_list = MetadataService.get_metadata_by_type(category.id) or []
        product = Product(**data)
        product.category = category
        product.cover = cover

        for metadata in metadata_list:
            value = metadata_value.get(metadata.id, None)
            if metadata.required and not value:
                return METADATA_NOT_FULL.jsonify()
            if metadata.value_mode == Metadata.VALUE_MODE_MUTI_SELECT:
                value = ','.join(value) if isinstance(value, (tuple, list)) else value
            product_metadata = ProductMetadata(
                metadata_id=metadata.id,
                value=value,
                name=metadata.screen_name,
            )
            product.extData.append(product_metadata)

        for k, v in contents.items():
            product.contents.append(
                ProductContent(language_code=k,
                               summary=v.get('summary'),
                               detail=v.get('description')),
            )
        ProductService.save(product)
        print(data)

    @route('/filter', methods=['POST'])
    def filter(self):
        # print('-!!!!'
        #       , ProductService.filter())
        param, _ = product_filter_param.load(request.get_json())
        logger.info('收到商品查询请求：{}', param)
        brand_id = param.pop('brand_id', None)
        brand = BrandService.get_brand_by_id(brand_id)
        if brand:
            param['brand_id'] = brand.id
        # 币种转换
        price_info = param.pop('price', None)
        min_price = None
        max_price = None

        if price_info:
            currency = price_info.pop('currency', None)
            min_price = price_info.pop('start', 0)
            max_price = price_info.pop('end', 0)

            if currency and (min_price or max_price):
                # 币种存在, 则需要进行转换
                currency = CurrencyService.get_currency_by_id(currency)
                if not currency:
                    return CURRENCY_NOT_EXIST.jsonify()
                if not currency.is_main_currency():
                    # 如果不是主币种,则要转换
                    from decimal import Decimal
                    if min_price:
                        min_price = Decimal.from_float(min_price) / currency.rate
                    if max_price:
                        max_price = Decimal.from_float(max_price) / currency.rate
        currency = param.pop('currency', None)

        if not currency:
            currency = CurrencyService.get_main_currency()

        data, pagination = ProductService.filter(
            min_price=min_price,
            max_price=max_price,
            **param,  # 其他参数不用做处理，直接塞进去
        )
        # if 'category_id' in param:
        # pass
        #
        # #把RMB转成美元，汇率为平均值,
        # # 未传值最大值：999999，最小默认为：0
        # average_price_max = param.get('average_price_max')
        # average_price_min = param.get('average_price_min')
        # if str(average_price_max) < str(average_price_min):
        #    return param_error.jsonify_with({
        #             'error':'最大价格不能小于最小价格！'})
        # else:
        #     if average_price_max is None:
        #         average_price_max = 999999
        #         rmb_price_max = average_price_max / 6.6423
        #         param['average_price_max'] = round(rmb_price_max, 4)
        #     else:
        #         rmb_price_max = average_price_max/6.6423
        #         param['average_price_max'] = round(rmb_price_max,4)
        #
        #     if average_price_min is None:
        #         average_price_min = 0
        #         param['average_price_min'] = average_price_min
        #     else:
        #         rmb_price_min = average_price_min/6.6423
        #         param['average_price_min'] = round(rmb_price_min,4)
        #
        #     #格式化查询日期，如果为空给一个最小值和一个当前系统日期
        #     start_publish_date = param.get('start_publish_date')
        #     end_publish_date =  param.get('end_publish_date')
        #     if  start_publish_date and end_publish_date:
        #         if start_publish_date > end_publish_date:
        #             return param_error.jsonify_with({
        #                 'error':'开始时间不能大于结束时间。'
        #             })
        #     else:
        #         if start_publish_date is None:
        #             start_publish_date = '1900-1-1'
        #             param['start_publish_date'] = start_publish_date
        #         if end_publish_date is None:
        #             end_publish_date = datetime.now()
        #             end_publish_date = end_publish_date.strftime('%Y%m%d')
        #             param['end_publish_date'] = end_publish_date
        #
        #     data, pagination = ProductService.filter(**param)
        product_list_schema = ProductSchema(many=True, context={'currency': currency})
        return query_schema.jsonify_with(
            items=product_list_schema.dump(data).data,
            pagination=pagination
        )

    @route('/<product_id>/brand', methods=['GET'])
    def filter_brand(self, product_id):
        product = ProductService.get_by_id(product_id)
        if not product:
            abort(404)

        brand = BrandService.get_brand_by_id(product.brand_id)
        if not brand:
            abort(404)

        currency = request.args.get('currency_id', None)
        limit = request.args.get('limit', None)
        if not currency:
            currency = CurrencyService.get_main_currency()
        else:
            currency = CurrencyService.get_currency_by_id(currency)
            if not currency:
                abort(404)
        brand_product = ProductService.get_same_brand_product_list(product, limit=limit)
        if brand_product:
            product_list_schema = ProductSchema(many=True, context={'currency': currency})
            return query_schema.jsonify_with(
                items=product_list_schema.dump(brand_product).data
            )
